package model.savers;


import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;

import com.nightpiter.model.objects.Line;
import com.nightpiter.model.objects.Station;
import com.nightpiter.model.objects.Transfer;
import com.nightpiter.model.objects.Tunnel;

import model.MetroModel;
import model.objects.EdiLine;

public class StandardSaver implements MetroSaver{
	public static final String XML_VERSION = "1.0";
	private HashMap<Station, Integer> stations = new HashMap<Station, Integer>();
	private Dictionary<Line, Integer> lines = new Hashtable<Line, Integer>();
	
	@Override
	public void save(String path, MetroModel model) throws IOException {
		File t = new File(path);		
		if(!t.exists())		t.createNewFile();
		OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(path),"UTF-8");       		
		out.write("<?xml version=\"" + XML_VERSION +"\" encoding=\"utf-8\"?>\n");
		//TODO map version setting
		out.write("<map version=\"0.0\">\n");

		writeLines(model, out);        		
		writeStations(model, out);		
		writeTunnels(model, out);
		writeTransfers(model, out);
		out.write("</map>\n");
		out.close();
	}

	private void writeTunnels(MetroModel model, OutputStreamWriter out)
			throws IOException {
		out.write("<tunnels>\n");        		
		for(Tunnel tunnel: model.getTunnels()) {
			out.write("	<tunnel from=\"" + stations.get(tunnel.getFromStation()) 
					+ "\" to=\"" + stations.get(tunnel.getToStation())
					+ "\" line=\"" + lines.get(tunnel.getLine()) 
					+ "\" time=\"" + tunnel.getTime() + "\" smooth=\"" + tunnel.isSmooth() + "\" />\n");    				
		}
		out.write("</tunnels>\n");
	}
	
	private void writeTransfers(MetroModel model, OutputStreamWriter out)
	throws IOException {
		out.write("<transfers>\n");        		
		for(Transfer transfer: model.getTransfers()) {
			out.write("	<transfer from=\"" + stations.get(transfer.getFromStation()) 
					+ "\" to=\"" + stations.get(transfer.getToStation())					 
					+ "\" time=\"" + transfer.getTime() + "\" />\n");    				
		}
		out.write("</transfers>\n");
}

	private void writeStations(MetroModel model, OutputStreamWriter out)
			throws IOException {
		out.write("<stations>\n");        		
		int i =0;
		for(Station station: model) {
			out.write("	<station id=\"" + i + "\">\n");
			stations.put(station, i);
			out.write("		<name dx=\"" + station.getLabelX() + "\" dy=\"" 
					+ station.getLabelY() + "\" angle=\"" + station.getLabelAngle() 
					+ "\" visible=\"" + station.isLabelVisible() + "\">" 
					+ station.getName() + "</name>\n");
			
			if(station.getOpenTime()!=null && station.getCloseTime()!=null) {
				out.write("		<schedule open=\""+ station.getOpenTime()+"\" " 
						+ "close=\""+station.getCloseTime()+ "\" />\n");
			}
			else { out.write("		<schedule open=\"00:00\" close=\"00:00\" />\n");
			}
			
			out.write("		<position x=\"" + station.getPosition().x 
					+ "\" y=\"" + station.getPosition().y + "\" />\n");
			
			if(station.getLocation()!=null)	{
				out.write("		<location latitude=\"" + station.getLocation().x 
						+ "\" longitude=\"" + station.getLocation().y + "\" />\n");
			} else {
				out.write("		<location latitude=\"0\" longitude=\"0\" />\n");
			}
			
			out.write("	</station>\n");
			i++;
			
		}
		out.write("</stations>\n");
	}

	private void writeLines(MetroModel model, OutputStreamWriter out)
			throws IOException {
		int i=0;
		out.write("<lines>\n");
		for(Line line: model.getLines()){
			out.write("	<line id=\"" + i + "\" ");
			out.write("color=\"" + colorToHex(new Color(line.getColor())) + "\">\n");
			out.write("		<name>" + line.getName() + "</name>\n" );
			out.write("	</line>\n");
			lines.put(line, i);
			i++;
		}
		out.write("</lines>\n");
	}
	
	private String colorToHex(Color color) {
		String c = "#";
		
		c+=numberToLetter(color.getRed()/16);
		c+=numberToLetter(color.getRed()%16);
		c+=numberToLetter(color.getGreen()/16);
		c+=numberToLetter(color.getGreen()%16);
		c+=numberToLetter(color.getBlue()/16);
		c+=numberToLetter(color.getBlue()%16);
		return c;
	}
	
	private char numberToLetter(int num) {
		
		switch(num) {
		case 0:
			return '0';
		case 1:
			return '1';
		case 2:
			return '2';
		case 3:
			return '3';
		case 4:
			return '4';
		case 5:
			return '5';
		case 6:
			return '6';
		case 7:
			return '7';
		case 8:
			return '8';
		case 9:
			return '9';
		case 10:
			return 'A';
		case 11:
			return 'B';
		case 12:
			return 'C';
		case 13:
			return 'D';
		case 14:
			return 'E';
		case 15:
			return 'F';
		}
		return '-';
	}

}
